package sg.edu.nus.iss.billing.gui;

import java.awt.*;
import java.awt.event.*;
import java.io.FileInputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.swing.*;

import sg.edu.nus.iss.billing.BillingApplication;
import sg.edu.nus.iss.billing.BillingConstants;
import sg.edu.nus.iss.billing.BillingConstants.SystemState;
import sg.edu.nus.iss.billing.controller.CustAccountController;
import sg.edu.nus.iss.billing.exceptions.ControllerException;
import sg.edu.nus.iss.billing.model.account.Account;
import sg.edu.nus.iss.billing.model.account.Account.CustomerStatus;
import sg.edu.nus.iss.billing.model.subscription.AdditionalChannelSubscription;
import sg.edu.nus.iss.billing.model.subscription.CableSubscription;
import sg.edu.nus.iss.billing.model.subscription.ISubscribable;
import sg.edu.nus.iss.billing.model.subscription.Service;
import sg.edu.nus.iss.billing.model.subscription.Subscription;
import sg.edu.nus.iss.billing.model.user.User.SystemRole;

/**
 * @author Yeo Hee Ling, Ananda, Saravana
 *
 */
public class CustomerPanel extends JPanel implements ActionListener {
	
	private static final long serialVersionUID = 1L;
	
	// Declaration of Global Variables.
	private Account account;
	private Properties properties;
	private BillingApplication billingAppl;
	private JPanel searchResultPanel;
	private JComboBox cbCustStatus;
	private JTextArea txtAddress;
	private JButton btnRegister, btnEdit, btnUpdate, btnClear, btnSearchResult;
	private JTextField txtAccount, txtName, txtNric, txtPostalCd, txtContactNo;
	private JCheckBox jcbSports, jcbTravel, jcbPhotography, jcbGaming, jcbShopping, jcbOnlineChat;
	private JLabel lblAccount, lblName, lblNric, lblAddress, lblPostalCd, lblContactNo, lblInterest, lblCustStatus;
	private String[] custStatusOption = {CustomerStatus.ACTIVE.toString(), CustomerStatus.INACTIVE.toString()};
	private DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
	
	// Class Constructor.
	public CustomerPanel(BillingApplication billingAppl, SystemState selectedMode, Account account, JPanel searchResultPanel) {
		this.account = account;
		this.billingAppl = billingAppl;
		this.searchResultPanel = searchResultPanel;
		this.setOpaque(false);
		
		loadConfiguration();
		
		boolean editable = true;
		if(SystemState.CUSTOMER_VIEW == selectedMode)
			editable = false;
		
		JPanel customerPanel = new JPanel();
		customerPanel.setOpaque(false);
        customerPanel.setLayout(new BorderLayout());
        customerPanel.add(registerEditCustomerPanel(selectedMode, editable), BorderLayout.CENTER);
        
        if(SystemState.CUSTOMER_UPDATE == selectedMode || SystemState.CUSTOMER_VIEW == selectedMode) {
        	populateCustomerDetails();
        }
        
        add(customerPanel);
	}
	
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == btnRegister) {
			try {
				String name = txtName.getText().trim();
				String nric = txtNric.getText().trim();
				String addr = txtAddress.getText().trim();
				String postalCd = txtPostalCd.getText().trim();
				String contactNo = txtContactNo.getText().trim();
				List<String> listOfInterests = getSelectedInterests();
				
				CustAccountController custAccountController = new CustAccountController();
				custAccountController.registerCustAccount(name, nric, addr, postalCd, contactNo, listOfInterests);
				JOptionPane.showMessageDialog(this, properties.getProperty("info.message.registerSuccessful"), properties.getProperty("title.registerCustomer"), JOptionPane.INFORMATION_MESSAGE);
				billingAppl.displayPage(new CustomerPanel(billingAppl, SystemState.CUSTOMER_REGISTER, null, null));
			}
			catch(ControllerException ex) {
				JOptionPane.showMessageDialog(this, ex.getMessage(), properties.getProperty("title.registerCustomer"), JOptionPane.ERROR_MESSAGE);
				return;
			}
		}
		else if(e.getSource() == btnUpdate) {
			try {
				CustomerStatus custStatus = CustomerStatus.valueOf(cbCustStatus.getSelectedItem().toString());
				if(account.getStatus() != custStatus) {
					if(CustomerStatus.INACTIVE == custStatus) {
						int res = JOptionPane.showConfirmDialog(null, properties.getProperty("info.message.inactiveCfmMsg"), properties.getProperty("title.updateCustomer"), JOptionPane.OK_CANCEL_OPTION);
						if(res != 0)
							return;
					}
				}
				
				account.setCustomerName(txtName.getText().trim());
				account.setCustomerNRIC(txtNric.getText().trim());
				account.setBillingAddress(txtAddress.getText().trim());
				account.setPostalCode(txtPostalCd.getText().trim());
				account.setTelephoneNo(txtContactNo.getText().trim());
				account.setStatus(CustomerStatus.valueOf(cbCustStatus.getSelectedItem().toString()));
				account.setInterests(getSelectedInterests());
				
				// Terminate all subscription upon inactive account.
				terminateSubscriptionForInactiveAccount();
				
				CustAccountController custAccountController = new CustAccountController();
				custAccountController.updateCustAccount(account);
				JOptionPane.showMessageDialog(this, properties.getProperty("info.message.updateSuccessful"), properties.getProperty("title.updateCustomer"), JOptionPane.INFORMATION_MESSAGE);
			}
			catch(ControllerException ex) {
				JOptionPane.showMessageDialog(this, ex.getMessage(), properties.getProperty("title.updateCustomer"), JOptionPane.ERROR_MESSAGE);
				return;
			}
		}
		else if(e.getSource() == btnClear) {
			txtName.setText("");
			txtNric.setText("");
			txtAddress.setText("");
			txtPostalCd.setText("");
			txtContactNo.setText("");
			jcbSports.setSelected(false);
			jcbTravel.setSelected(false);
			jcbPhotography.setSelected(false);
			jcbGaming.setSelected(false);
			jcbShopping.setSelected(false);
			jcbOnlineChat.setSelected(false);
			cbCustStatus.setSelectedIndex(0);
		}
		else if(e.getSource() == btnEdit) {
			billingAppl.displayPage(new CustomerPanel(billingAppl, SystemState.CUSTOMER_UPDATE, account, searchResultPanel));
		}
		else if(e.getSource() == btnSearchResult) {
			billingAppl.displayPage(searchResultPanel);
		}
	}
	
	private List<String> getSelectedInterests() {
		List<String> listOfInterests = new ArrayList<String>();
		if(jcbSports.isSelected())
			listOfInterests.add(jcbSports.getText());
		if(jcbTravel.isSelected())
			listOfInterests.add(jcbTravel.getText());
		if(jcbPhotography.isSelected())
			listOfInterests.add(jcbPhotography.getText());
		if(jcbGaming.isSelected())
			listOfInterests.add(jcbGaming.getText());
		if(jcbShopping.isSelected())
			listOfInterests.add(jcbShopping.getText());
		if(jcbOnlineChat.isSelected())
			listOfInterests.add(jcbOnlineChat.getText());
		
		return listOfInterests;
	}
	
	private void loadConfiguration() {
		try {
			properties = new Properties();
			FileInputStream in = new FileInputStream(BillingConstants.PROPERTIES_CUSTOMER);
			properties.load(in);
			in.close();
		}
		catch(Exception ex) {
			ex.printStackTrace();
		}
	}
	
	private void populateCustomerDetails() {
		if(account != null) {
			txtAccount.setText(account.getAccountNo());
			txtName.setText(account.getCustomerName());
			txtNric.setText(account.getCustomerNRIC());
			txtAddress.setText(account.getBillingAddress());
			txtPostalCd.setText(account.getPostalCode());
			txtContactNo.setText(account.getTelephoneNo());
			cbCustStatus.setSelectedItem(account.getStatus().toString());
			
			List<String> interests = account.getInterests();
			if(interests != null && interests.size() > 0) {
				Iterator<String> iter = interests.iterator();
				while(iter.hasNext()) {
					String interest = iter.next();
					if(jcbSports.getText().equals(interest))
						jcbSports.setSelected(true);
					else if(jcbTravel.getText().equals(interest))
						jcbTravel.setSelected(true);
					else if(jcbPhotography.getText().equals(interest))
						jcbPhotography.setSelected(true);
					else if(jcbGaming.getText().equals(interest))
						jcbGaming.setSelected(true);
					else if(jcbShopping.getText().equals(interest))
						jcbShopping.setSelected(true);
					else if(jcbOnlineChat.getText().equals(interest))
						jcbOnlineChat.setSelected(true);
				}
			}
		}
	}
	
	private void terminateSubscriptionForInactiveAccount() {
		List<Subscription> subscriptions = account.getSubscriptions();
		List<Subscription> updatedSubscriptions = new ArrayList<Subscription>();
		
		Iterator<Subscription> subIter = subscriptions.iterator();
		while(subIter.hasNext()) {
			Subscription subscription = subIter.next();
			
			if(subscription.getDateTerminated() != null && !"".equals(subscription.getDateTerminated())) {
				updatedSubscriptions.add(subscription);
			}
			else {
				List<ISubscribable> services = subscription.getServices();
				List<ISubscribable> updatedServices = new ArrayList<ISubscribable>();
				
				for(int n = 0; n < services.size(); n++) {
					Service service = (Service)services.get(n);
					
					if(service.getDateTerminated() != null && !"".equals(service.getDateTerminated())) {
						updatedServices.add(service);
					}
					else {
						service.setDateTerminated(sdf.format(new Date()));
						updatedServices.add(service);
					}
				}
				
				// To terminate additional channel subscription.
				if(subscription instanceof CableSubscription) {
					List<AdditionalChannelSubscription> channelList = ((CableSubscription)subscription).getAdditionalChannelNames();
					if(channelList != null && channelList.size() > 0) {
						for(int n = 0; n < channelList.size(); n++) {
							AdditionalChannelSubscription addChnlSub = (AdditionalChannelSubscription)channelList.get(n);
							addChnlSub.setDateTerminated(sdf.format(new Date()));
						}
					}
				}
				
				subscription.setServices(updatedServices);
				subscription.setDateTerminated(sdf.format(new Date()));
				updatedSubscriptions.add(subscription);
			}
		}
		account.setSubscriptions(updatedSubscriptions);
	}
	
	private JPanel registerEditCustomerPanel(SystemState selectedMode, boolean editable) {
		// 1. To determine the title of the customer panel.
		String customerPanelTitle = "";
		if(SystemState.CUSTOMER_REGISTER == selectedMode)
			customerPanelTitle = properties.getProperty("label.customer.header.register");
		else if(SystemState.CUSTOMER_VIEW == selectedMode)
			customerPanelTitle = properties.getProperty("label.customer.header.view");
		else if(SystemState.CUSTOMER_UPDATE == selectedMode)
			customerPanelTitle = properties.getProperty("label.customer.header.update");
		
		// 2. Construct Customer Details Panel
		GridBagLayout customerGridLayout = new GridBagLayout();
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.insets = new Insets(5, 5, 5, 5);
		
		JPanel customerDetailPanel = new JPanel(customerGridLayout);
		customerDetailPanel.setOpaque(false);
		
		constraints.fill = GridBagConstraints.HORIZONTAL;
		constraints.gridx = 0;
		constraints.gridy = 0;
		lblAccount = new JLabel(properties.getProperty("label.customer.accountNo"));
		lblAccount.setHorizontalAlignment(JLabel.RIGHT);
		customerDetailPanel.add(lblAccount, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 0;
		txtAccount = new JTextField(20);
		txtAccount.setText("-");
		txtAccount.setEditable(false);
		txtAccount.setBorder(BorderFactory.createEmptyBorder());
		customerDetailPanel.add(txtAccount, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 1;
		lblName = new JLabel(properties.getProperty("label.customer.name"));
		lblName.setHorizontalAlignment(JLabel.RIGHT);
		customerDetailPanel.add(lblName, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 1;
		txtName = new JTextField(20);
		txtName.setEditable(editable);
		customerDetailPanel.add(txtName, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 2;
		lblNric = new JLabel(properties.getProperty("label.customer.nric"));
		lblNric.setHorizontalAlignment(JLabel.RIGHT);
		customerDetailPanel.add(lblNric, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 2;
		txtNric = new JTextField(8);
		txtNric.addKeyListener(new KeyAdapter() {
			public void keyTyped(KeyEvent e) {
				if(txtNric.getText().length() >= 9)
					e.consume();
			}
		});
		if(SystemState.CUSTOMER_VIEW == selectedMode || SystemState.CUSTOMER_UPDATE == selectedMode) {
			txtNric.setEditable(false);
			txtNric.setBorder(BorderFactory.createEmptyBorder());
		}
		customerDetailPanel.add(txtNric, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 3;
		lblAddress = new JLabel(properties.getProperty("label.customer.address"));
		lblAddress.setHorizontalAlignment(JLabel.RIGHT);
		customerDetailPanel.add(lblAddress, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 3;
		txtAddress = new JTextArea(5, 20);
		txtAddress.setEditable(editable);
		customerDetailPanel.add(new JScrollPane(txtAddress), constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 4;
		lblPostalCd = new JLabel(properties.getProperty("label.customer.postal"));
		lblPostalCd.setHorizontalAlignment(JLabel.RIGHT);
		customerDetailPanel.add(lblPostalCd, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 4;
		txtPostalCd = new JTextField(20);
		txtPostalCd.setEditable(editable);
		txtPostalCd.addKeyListener(new KeyAdapter() {
			public void keyTyped(KeyEvent e) {
				if(txtPostalCd.getText().length() >= 6)
					e.consume();
			}
		});
		customerDetailPanel.add(txtPostalCd, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 5;
		lblContactNo= new JLabel(properties.getProperty("label.customer.contact"));
		lblContactNo.setHorizontalAlignment(JLabel.RIGHT);
		customerDetailPanel.add(lblContactNo, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 5;
		txtContactNo = new JTextField(20);
		txtContactNo.setEditable(editable);
		txtContactNo.addKeyListener(new KeyAdapter() {
			public void keyTyped(KeyEvent e) {
				if(txtContactNo.getText().length() >= 8)
					e.consume();
			}
		});
		customerDetailPanel.add(txtContactNo, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 6;
		lblInterest= new JLabel(properties.getProperty("label.customer.interests"));
		lblInterest.setHorizontalAlignment(JLabel.RIGHT);
		customerDetailPanel.add(lblInterest, constraints);
		
		JPanel interestPanel = new JPanel();
		interestPanel.setOpaque(false);
		interestPanel.setLayout(new GridLayout(0, 3, 0, 0));
		
		jcbSports = new JCheckBox(properties.getProperty("label.customer.interest.sports"));
		jcbSports.setEnabled(editable);
		jcbSports.setOpaque(false);
		jcbTravel = new JCheckBox(properties.getProperty("label.customer.interest.travel"));
		jcbTravel.setEnabled(editable);
		jcbTravel.setOpaque(false);
		jcbPhotography = new JCheckBox(properties.getProperty("label.customer.interest.photography"));
		jcbPhotography.setEnabled(editable);
		jcbPhotography.setOpaque(false);
		jcbGaming = new JCheckBox(properties.getProperty("label.customer.interest.gaming"));
		jcbGaming.setEnabled(editable);
		jcbGaming.setOpaque(false);
		jcbShopping = new JCheckBox(properties.getProperty("label.customer.interest.shopping"));
		jcbShopping.setEnabled(editable);
		jcbShopping.setOpaque(false);
		jcbOnlineChat = new JCheckBox(properties.getProperty("label.customer.interest.onlineChat"));
		jcbOnlineChat.setEnabled(editable);
		jcbOnlineChat.setOpaque(false);
		interestPanel.add(jcbSports);
		interestPanel.add(jcbTravel);
		interestPanel.add(jcbPhotography);
		interestPanel.add(jcbGaming);
		interestPanel.add(jcbShopping);
		interestPanel.add(jcbOnlineChat);
		
		constraints.gridx = 1;
		constraints.gridy = 6;
		customerDetailPanel.add(interestPanel, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 7;
		lblCustStatus= new JLabel(properties.getProperty("label.customer.status"));
		lblCustStatus.setHorizontalAlignment(JLabel.RIGHT);
		customerDetailPanel.add(lblCustStatus, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 7;
		cbCustStatus = new JComboBox(custStatusOption);
		if(SystemState.CUSTOMER_REGISTER == selectedMode || SystemState.CUSTOMER_VIEW == selectedMode)
			cbCustStatus.setEnabled(false);
		else
			cbCustStatus.setEnabled(true);
		customerDetailPanel.add(cbCustStatus, constraints);
		
		JPanel buttonPanel = new JPanel();
		buttonPanel.setOpaque(false);
		buttonPanel.setLayout(new GridLayout(0, 2, 5, 0));
		
		if(SystemState.CUSTOMER_REGISTER == selectedMode) {
			btnRegister = new JButton(properties.getProperty("label.customer.button.register"));
			btnRegister.addActionListener(this);
			btnClear = new JButton(properties.getProperty("label.customer.button.clear"));
			btnClear.addActionListener(this);
			buttonPanel.add(btnRegister);
			buttonPanel.add(btnClear);
		}
		else if(SystemState.CUSTOMER_VIEW == selectedMode) {
			if(BillingApplication.getUserSession().getSystemRole() == SystemRole.ADMIN) {
				btnEdit = new JButton(properties.getProperty("label.customer.button.edit"));
				btnEdit.addActionListener(this);
				buttonPanel.add(btnEdit);
			}
			else {
				buttonPanel.add(new JLabel(""));
			}
			btnSearchResult = new JButton(properties.getProperty("label.customer.button.searchResult"));
			btnSearchResult.addActionListener(this);
			buttonPanel.add(btnSearchResult);
		}
		else if(SystemState.CUSTOMER_UPDATE == selectedMode) {
			btnUpdate = new JButton(properties.getProperty("label.customer.button.update"));
			btnUpdate.addActionListener(this);
			btnSearchResult = new JButton(properties.getProperty("label.customer.button.searchResult"));
			btnSearchResult.addActionListener(this);
			buttonPanel.add(btnUpdate);
			buttonPanel.add(btnSearchResult);
		}
		
		constraints.gridx = 1;
		constraints.gridy = 8;
		customerDetailPanel.add(buttonPanel, constraints);
		
		// 3. Construct Header Panel
		JPanel headerPanel = new JPanel();
		headerPanel.setOpaque(false);
		headerPanel.setLayout(new GridLayout(0, 1, 10, 10));
		
		JLabel msgLabel = new JLabel(customerPanelTitle);
		msgLabel.setFont(new Font("Tahoma", Font.BOLD, 18));
		msgLabel.setHorizontalAlignment(SwingConstants.CENTER);
		headerPanel.add(msgLabel);
		
		ImageIcon imgDivider = new ImageIcon("./images/divider.jpg");
		JLabel lblDivider = new JLabel(imgDivider);
		headerPanel.add(lblDivider);
		
		JPanel customerPanel = new JPanel();
		customerPanel.setOpaque(false);
		customerPanel.setLayout(new BorderLayout());
		customerPanel.add(headerPanel, BorderLayout.NORTH);
		customerPanel.add(customerDetailPanel, BorderLayout.CENTER);
		
		return customerPanel;
	}
}
